Routing specs自動生成
regressor
regressor gemではcontrollerをベースにcontroller, action, path中のparameterを取得してexampleを組み立てている
controllersの一覧取得
code:ruby
Rails.application.eager_load!
ApplicationController.descendants
controller nameから情報を取り出す
code:ruby
controller_name = "UsersController"
controller = controller_name.constantize
controller_path = controller.controller_path
# => "users"
action_methods = controller.action_methods
action_method = action_methods.first
journey_route = Rails.application.routes.routes.first do |route|
route.defaults:controller.to_sym == controller_path.to_sym && route.defaults:action.to_sym == action_method.to_sym end
journey_route.required_parts
url = Rails.application.routes.url_helpers.url_for({controller: 'users', action: 'hello', only_path: true}.merge({user_id: '1'}))
=> "/users/1/hello"
code:ruby
def generate_example(journey_route, controller_path, action_method, required_parts, url)
case journey_route.verb
when 'GET'
"it { should route(:get, '#{url}').to('#{controller_path}##{action_method}', #{required_parts}) }" when 'POST'
"it { should route(:post, '#{url}').to('#{controller_path}##{action_method}', #{required_parts}) } " when 'PUT'
"it { should route(:put, '#{url}').to('#{controller_path}##{action_method}', #{required_parts}) } " when 'PATCH'
"it { should route(:patch, '#{url}').to('#{controller_path}##{action_method}', #{required_parts}) } " when 'DELETE'
"it { should route(:delete, '#{url}').to('#{controller_path}##{action_method}', #{required_parts}) } " end
end
良くない点
shoulda-matchers, fakerに依存している
gem自体にrouting spec以外の役割もある
RSpec限定
controller起点なのでroutes.rbに記述はあるがcontrollersが存在しない場合を検出できない
その場合どこかでエラー吐いてくれるんだっけ、エラーにならずにRailsが起動するところまでは確認
controller起点とroutes起点の両方で突き合わせてエラーを出すととても親切
controller.action_methods起点なのでcontrollerにaction method (public instance method) が存在しない場合は検証できない
RAILS_ENV=test rails generate regressor:controllerを毎回routesを足すたびに実行する
テストケースは一個だけ書いておいて(もしくはgenerateで初回だけ生成)、内部で動的にテストしてくれたほうが楽では?
route_tractor
Rails.application.routes側から生成している
よくない点
死んでる
毎回rake taskを実行する必要がある
traceroute
毎回rake taskを実行する必要がある
bin/rails routes
bin/rails routesを真似る
RoutesInspectorはそれ以外の目的で使うな、とコメントに書いてある code:ruby
ActionDispatch::Routing::RoutesInspector.new(
Rails.application.routes.routes
).format(
ActionDispatch::Routing::ConsoleFormatter::Sheet.new
)
code:ruby
journey_route = Rails.application.routes.routes.first
wrapper = ActionDispatch::Routing::RouteWrapper.new journey_route
wrapper.name
=> "user_post"
wrapper.verb
=> "GET"
wrapper.path
=> "/users/:user_id/posts/:id(.:format)"
wrapper.reqs
=> "posts#show"
routing関連のassertion
assert_generates
与えたoptionsでActionDispatch::Routing::RouteSet#generate_extrasが生成するpathと、期待するpathが一致するかどうか
assert_recognizes
与えたpathでActionDispatch::Routing::RouteSet#recognize_pathが解釈するoptionsと、期待するoptionsが一致するかどうか
assert_routing
assert_generatesとassert_recognizesの両方
rspec-rails
route_to matcher
assert_recognizesを使う
内部的にはActionDispatch::Routing::RouteSet#recognize_path
be_routable matcher
ActionDispatch::Routing::RouteSet#recognize_pathを使う
参考